"""
通用文档信息抽取 - 模板配置系统

支持多种文档类型的字段定义和配置管理
"""

import os
import yaml
import json
from pathlib import Path
from typing import Dict, List, Any, Optional
import logging

logger = logging.getLogger(__name__)


class DocumentTemplate:
    """文档模板类"""
    
    def __init__(self, template_config: Dict[str, Any]):
        """初始化文档模板
        
        Args:
            template_config: 模板配置字典
        """
        self.name = template_config.get('name') or template_config.get('document_type', 'unknown')
        self.display_name = template_config.get('display_name', self.name)
        self.description = template_config.get('description', '')
        self.fields = template_config.get('fields', [])
        self.categories = template_config.get('categories', {})
        self.validation_rules = template_config.get('validation_rules', {})
        self.prompt_template = template_config.get('prompt_template', '')
        
    def get_field_names(self) -> List[str]:
        """获取所有字段名称"""
        field_names = []
        for field in self.fields:
            if isinstance(field, dict):
                # 兼容两种字段格式：{name: "..."} 和 {field_name: "..."}
                field_name = field.get('name') or field.get('field_name')
                if field_name:
                    field_names.append(field_name)
        return field_names
    
    def get_field_info(self, field_name: str) -> Dict[str, Any]:
        """获取字段详细信息"""
        for field in self.fields:
            if isinstance(field, dict):
                # 兼容两种字段格式：{name: "..."} 和 {field_name: "..."}
                name = field.get('name') or field.get('field_name')
                if name == field_name:
                    # 标准化字段信息格式
                    field_info = field.copy()
                    if 'field_name' in field_info:
                        field_info['name'] = field_info.pop('field_name')
                    if 'field_type' in field_info:
                        field_info['type'] = field_info.pop('field_type')
                    return field_info
        return {}
    
    def validate_extracted_data(self, data: Dict[str, str]) -> List[str]:
        """验证抽取的数据
        
        Args:
            data: 抽取的数据
            
        Returns:
            错误信息列表
        """
        errors = []
        field_names = self.get_field_names()
        
        # 检查必填字段
        for field_name in field_names:
            field_info = self.get_field_info(field_name)
            if field_info.get('required', True):
                if field_name not in data or data[field_name] in ['', '未找到', None]:
                    errors.append(f"必填字段缺失: {field_name}")
        
        # 检查字段格式
        for field_name, value in data.items():
            if field_name in field_names:
                field_info = self.get_field_info(field_name)
                field_type = field_info.get('type', 'text')
                
                if field_type == 'number' and value != '未找到':
                    try:
                        float(value.replace(',', '').replace('元', '').replace('万', ''))
                    except ValueError:
                        errors.append(f"字段格式错误: {field_name} 应为数字")
                        
                elif field_type == 'date' and value != '未找到':
                    import re
                    if not re.match(r'\d{4}[年-]\d{1,2}[月-]\d{1,2}[日]?', value):
                        errors.append(f"字段格式错误: {field_name} 应为日期格式")
        
        return errors


class TemplateManager:
    """文档模板管理器"""
    
    def __init__(self, templates_dir: str = "config/templates"):
        """初始化模板管理器
        
        Args:
            templates_dir: 模板配置目录
        """
        self.templates_dir = Path(templates_dir)
        self.templates_dir.mkdir(parents=True, exist_ok=True)
        self.templates = {}
        self._load_templates()
    
    def _load_templates(self):
        """加载所有模板"""
        # 优先加载YAML配置文件中的模板
        for template_file in self.templates_dir.glob("*.yaml"):
            try:
                with open(template_file, 'r', encoding='utf-8') as f:
                    template_config = yaml.safe_load(f)
                    template = DocumentTemplate(template_config)
                    # 使用文件名（不含扩展名）作为模板名称
                    template_name = template_file.stem
                    self.templates[template_name] = template
                    logger.info(f"已加载模板: {template.display_name} ({template_name})")
            except Exception as e:
                logger.error(f"加载模板失败 {template_file}: {e}")
        
        # 如果没有加载到任何模板，则创建默认模板
        if not self.templates:
            self.create_default_templates()
    
    def get_template(self, template_name: str) -> Optional[DocumentTemplate]:
        """获取指定模板"""
        return self.templates.get(template_name)
    
    def list_templates(self) -> List[str]:
        """列出所有可用模板"""
        return list(self.templates.keys())
    
    def get_template_info(self) -> Dict[str, Dict[str, Any]]:
        """获取所有模板信息"""
        return {
            name: {
                'display_name': template.display_name,
                'description': template.description,
                'field_count': len(template.get_field_names())
            }
            for name, template in self.templates.items()
        }
    
    def create_default_templates(self):
        """创建默认模板"""
        default_templates = {
            'contract': self._get_contract_template(),
            'invoice': self._get_invoice_template(),
            'resume': self._get_resume_template(),
            'medical_report': self._get_medical_report_template(),
            'id_card': self._get_id_card_template()
        }
        
        for template_name, template_config in default_templates.items():
            template_file = self.templates_dir / f"{template_name}.yaml"
            with open(template_file, 'w', encoding='utf-8') as f:
                yaml.dump(template_config, f, ensure_ascii=False, indent=2)
            logger.info(f"已创建默认模板: {template_file}")
        
        # 重新加载模板
        self._load_templates()
    
    def _get_contract_template(self) -> Dict[str, Any]:
        """获取模板配置"""
        return {
            'name': 'contract',
            'display_name': '文档',
            'description': '商业信息抽取模板',
            'fields': [
                {'name': '名称', 'type': 'text', 'required': True, 'description': '的具体名称'},
                {'name': '编号', 'type': 'text', 'required': True, 'description': '唯一标识符'},
                {'name': '甲方名称', 'type': 'text', 'required': True, 'description': '甲方公司名称'},
                {'name': '甲方地址', 'type': 'text', 'required': False, 'description': '甲方公司地址'},
                {'name': '甲方联系人', 'type': 'text', 'required': False, 'description': '甲方联系人姓名'},
                {'name': '乙方名称', 'type': 'text', 'required': True, 'description': '乙方公司名称'},
                {'name': '乙方地址', 'type': 'text', 'required': False, 'description': '乙方公司地址'},
                {'name': '乙方联系人', 'type': 'text', 'required': False, 'description': '乙方联系人姓名'},
                {'name': '金额', 'type': 'number', 'required': True, 'description': '总金额'},
                {'name': '期限', 'type': 'text', 'required': True, 'description': '有效期'},
                {'name': '签署日期', 'type': 'date', 'required': True, 'description': '签署日期'},
                {'name': '生效日期', 'type': 'date', 'required': False, 'description': '生效日期'},
                {'name': '履行地点', 'type': 'text', 'required': False, 'description': '履行地点'},
                {'name': '付款方式', 'type': 'text', 'required': False, 'description': '付款方式说明'},
                {'name': '违约责任', 'type': 'text', 'required': False, 'description': '违约责任条款'}
            ],
            'categories': {
                'basic_info': ['名称', '编号'],
                'parties': ['甲方名称', '甲方地址', '甲方联系人', '乙方名称', '乙方地址', '乙方联系人'],
                'terms': ['金额', '期限', '签署日期', '生效日期', '履行地点', '付款方式', '违约责任']
            }
        }
    
    def _get_invoice_template(self) -> Dict[str, Any]:
        """获取发票模板配置"""
        return {
            'name': 'invoice',
            'display_name': '发票文档',
            'description': '增值税发票信息抽取模板',
            'fields': [
                {'name': '发票代码', 'type': 'text', 'required': True, 'description': '发票代码'},
                {'name': '发票号码', 'type': 'text', 'required': True, 'description': '发票号码'},
                {'name': '开票日期', 'type': 'date', 'required': True, 'description': '开票日期'},
                {'name': '销售方名称', 'type': 'text', 'required': True, 'description': '销售方公司名称'},
                {'name': '销售方纳税人识别号', 'type': 'text', 'required': True, 'description': '销售方税号'},
                {'name': '销售方地址电话', 'type': 'text', 'required': False, 'description': '销售方地址和电话'},
                {'name': '销售方开户行账号', 'type': 'text', 'required': False, 'description': '销售方银行账号'},
                {'name': '购买方名称', 'type': 'text', 'required': True, 'description': '购买方公司名称'},
                {'name': '购买方纳税人识别号', 'type': 'text', 'required': False, 'description': '购买方税号'},
                {'name': '购买方地址电话', 'type': 'text', 'required': False, 'description': '购买方地址和电话'},
                {'name': '购买方开户行账号', 'type': 'text', 'required': False, 'description': '购买方银行账号'},
                {'name': '货物服务名称', 'type': 'text', 'required': True, 'description': '商品或服务名称'},
                {'name': '规格型号', 'type': 'text', 'required': False, 'description': '商品规格型号'},
                {'name': '单位', 'type': 'text', 'required': False, 'description': '计量单位'},
                {'name': '数量', 'type': 'number', 'required': False, 'description': '商品数量'},
                {'name': '单价', 'type': 'number', 'required': False, 'description': '商品单价'},
                {'name': '金额', 'type': 'number', 'required': True, 'description': '不含税金额'},
                {'name': '税率', 'type': 'text', 'required': False, 'description': '税率'},
                {'name': '税额', 'type': 'number', 'required': False, 'description': '税额'},
                {'name': '价税合计', 'type': 'number', 'required': True, 'description': '含税总金额'}
            ],
            'categories': {
                'basic_info': ['发票代码', '发票号码', '开票日期'],
                'seller': ['销售方名称', '销售方纳税人识别号', '销售方地址电话', '销售方开户行账号'],
                'buyer': ['购买方名称', '购买方纳税人识别号', '购买方地址电话', '购买方开户行账号'],
                'items': ['货物服务名称', '规格型号', '单位', '数量', '单价'],
                'amounts': ['金额', '税率', '税额', '价税合计']
            }
        }
    
    def _get_resume_template(self) -> Dict[str, Any]:
        """获取简历模板配置"""
        return {
            'name': 'resume',
            'display_name': '简历文档',
            'description': '个人简历信息抽取模板',
            'fields': [
                {'name': '姓名', 'type': 'text', 'required': True, 'description': '应聘者姓名'},
                {'name': '性别', 'type': 'text', 'required': False, 'description': '性别'},
                {'name': '年龄', 'type': 'number', 'required': False, 'description': '年龄'},
                {'name': '出生日期', 'type': 'date', 'required': False, 'description': '出生日期'},
                {'name': '联系电话', 'type': 'text', 'required': True, 'description': '联系电话'},
                {'name': '邮箱', 'type': 'text', 'required': False, 'description': '电子邮箱'},
                {'name': '现居地址', 'type': 'text', 'required': False, 'description': '现居住地址'},
                {'name': '籍贯', 'type': 'text', 'required': False, 'description': '籍贯'},
                {'name': '学历', 'type': 'text', 'required': True, 'description': '最高学历'},
                {'name': '毕业院校', 'type': 'text', 'required': False, 'description': '毕业学校'},
                {'name': '专业', 'type': 'text', 'required': False, 'description': '所学专业'},
                {'name': '毕业时间', 'type': 'date', 'required': False, 'description': '毕业时间'},
                {'name': '工作经验', 'type': 'text', 'required': False, 'description': '工作经验年限'},
                {'name': '当前职位', 'type': 'text', 'required': False, 'description': '当前工作职位'},
                {'name': '期望职位', 'type': 'text', 'required': False, 'description': '期望工作职位'},
                {'name': '期望薪资', 'type': 'text', 'required': False, 'description': '期望薪资'},
                {'name': '技能特长', 'type': 'text', 'required': False, 'description': '专业技能和特长'},
                {'name': '自我评价', 'type': 'text', 'required': False, 'description': '自我评价'}
            ],
            'categories': {
                'personal': ['姓名', '性别', '年龄', '出生日期', '联系电话', '邮箱', '现居地址', '籍贯'],
                'education': ['学历', '毕业院校', '专业', '毕业时间'],
                'career': ['工作经验', '当前职位', '期望职位', '期望薪资'],
                'skills': ['技能特长', '自我评价']
            }
        }
    
    def _get_medical_report_template(self) -> Dict[str, Any]:
        """获取医疗报告模板配置"""
        return {
            'name': 'medical_report',
            'display_name': '医疗报告',
            'description': '医疗检查报告信息抽取模板',
            'fields': [
                {'name': '患者姓名', 'type': 'text', 'required': True, 'description': '患者姓名'},
                {'name': '性别', 'type': 'text', 'required': False, 'description': '患者性别'},
                {'name': '年龄', 'type': 'number', 'required': False, 'description': '患者年龄'},
                {'name': '病历号', 'type': 'text', 'required': False, 'description': '病历编号'},
                {'name': '检查日期', 'type': 'date', 'required': True, 'description': '检查日期'},
                {'name': '检查项目', 'type': 'text', 'required': True, 'description': '检查项目名称'},
                {'name': '检查部位', 'type': 'text', 'required': False, 'description': '检查部位'},
                {'name': '临床诊断', 'type': 'text', 'required': False, 'description': '临床诊断'},
                {'name': '检查所见', 'type': 'text', 'required': False, 'description': '检查所见描述'},
                {'name': '检查结论', 'type': 'text', 'required': True, 'description': '检查结论'},
                {'name': '建议', 'type': 'text', 'required': False, 'description': '医生建议'},
                {'name': '报告医生', 'type': 'text', 'required': False, 'description': '报告医生'},
                {'name': '审核医生', 'type': 'text', 'required': False, 'description': '审核医生'},
                {'name': '医院名称', 'type': 'text', 'required': False, 'description': '医院名称'},
                {'name': '科室', 'type': 'text', 'required': False, 'description': '检查科室'}
            ],
            'categories': {
                'patient_info': ['患者姓名', '性别', '年龄', '病历号'],
                'exam_info': ['检查日期', '检查项目', '检查部位', '临床诊断'],
                'results': ['检查所见', '检查结论', '建议'],
                'medical_staff': ['报告医生', '审核医生', '医院名称', '科室']
            }
        }
    
    def _get_id_card_template(self) -> Dict[str, Any]:
        """获取身份证模板配置"""
        return {
            'name': 'id_card',
            'display_name': '身份证',
            'description': '身份证信息抽取模板',
            'fields': [
                {'name': '姓名', 'type': 'text', 'required': True, 'description': '姓名'},
                {'name': '性别', 'type': 'text', 'required': True, 'description': '性别'},
                {'name': '民族', 'type': 'text', 'required': True, 'description': '民族'},
                {'name': '出生日期', 'type': 'date', 'required': True, 'description': '出生日期'},
                {'name': '住址', 'type': 'text', 'required': True, 'description': '住址'},
                {'name': '身份证号码', 'type': 'text', 'required': True, 'description': '身份证号码'},
                {'name': '签发机关', 'type': 'text', 'required': False, 'description': '签发机关'},
                {'name': '有效期限', 'type': 'text', 'required': False, 'description': '有效期限'}
            ],
            'categories': {
                'personal_info': ['姓名', '性别', '民族', '出生日期', '住址', '身份证号码'],
                'card_info': ['签发机关', '有效期限']
            }
        }


# 单例模式的全局模板管理器
_template_manager = None

def get_template_manager() -> TemplateManager:
    """获取全局模板管理器"""
    global _template_manager
    if _template_manager is None:
        _template_manager = TemplateManager()
        if not _template_manager.list_templates():
            _template_manager.create_default_templates()
    return _template_manager